home *** CD-ROM | disk | FTP | other *** search
/ Pascal Super Library / Pascal Super Library (CW International)(1997).bin / LIBRARY / PAS_0493 / MODEY.PAS < prev    next >
Pascal/Delphi Source File  |  1993-04-15  |  6KB  |  182 lines

  1. {─ Fido Pascal Conference ────────────────────────────────────────────── PASCAL ─
  2. Msg  : 375 of 385
  3. From : Kai Rohrbacher                      2:241/7451.7         10 Apr 93  19:55
  4. To   : David Todd                          1:259/423.0
  5. Subj : Mode X/Y (was Re: Faster MOVE/FILLCHAR)
  6. ────────────────────────────────────────────────────────────────────────────────
  7. DT>  Hello Kai,
  8. DT>            I was wondering if you have time, (or patients) to explain
  9. DT>  MODE X.
  10. How comes me getting that honour? :-)
  11.  
  12.   Well,  I don't care much about Mode X (which is 320x240x256), but use Mode Y
  13.   (=320x200x256)  --at least I think that this mode is called "Mode Y" (as far
  14.   as  I  know, the terms were introduced by a series of Michael Abrash in "Dr.
  15.   Dobb's  Journal" (?)). Nevertheless, things are identical with the exception
  16.   of initialising the VGA card! So here we go; note that the ASM code examples
  17.   were taken from my ANIVGA-toolkit: the PASCAL-equivalents when given are "on
  18.   the  fly"  ASM->PASCAL  translations  for  improved  clarity (I hope...); in
  19.   doubt, rely on the ASM part.
  20.  
  21. MODE Y in a nutshell
  22. ~~~~~~~~~~~~~~~~~~~~
  23.  
  24.   Basically,  Mode  Y  works  like  this:  use  the BIOS to switch into normal
  25.   320x200x256  mode,  then reprogram the sequencer to unchain the 4 bitplanes.
  26.   This  results  in  a bitplaned VRAM layout very similiar to the EGA/VGA's 16
  27.   color modes: }
  28.  
  29. PROCEDURE InitGraph; ASSEMBLER;
  30. ASM
  31.   MOV AX,0013h
  32.   INT 10h
  33.   MOV DX,03C4h
  34.   MOV AL,04
  35.   OUT DX,AL
  36.   INC DX
  37.   IN  AL,DX
  38.   AND AL,0F7h
  39.   OR  AL,04
  40.   OUT DX,AL
  41.   MOV DX,03C4h
  42.   MOV AL,02
  43.   OUT DX,AL
  44.   INC DX
  45.   MOV AL,0Fh
  46.   OUT DX,AL
  47.   MOV AX,0A000h
  48.   MOV ES,AX
  49.   SUB DI,DI
  50.   MOV AX,DI
  51.   MOV CX,8000h
  52.   CLD
  53.   REP STOSW
  54.  
  55.   MOV DX,CRTAddress
  56.   MOV AL,14h
  57.   OUT DX,AL
  58.   INC DX
  59.   IN  AL,DX
  60.   AND AL,0BFh
  61.   OUT DX,AL
  62.   DEC DX
  63.   MOV AL,17h
  64.   OUT DX,AL
  65.   INC DX
  66.   IN  AL,DX
  67.   OR  AL,40h
  68.   OUT DX,AL
  69. END;
  70.  
  71. {
  72.   CRTAddress  and  StatusReg  are the port addresses for the VGA ports needed;
  73.   they  are 3B4h and 3BAh on a monochrome display and 3D4h and 3DAh on a color
  74.   display, but can be determined at run-time, too: }
  75.  
  76. ASM
  77.   MOV DX,3CCh
  78.   IN AL,DX
  79.   TEST AL,1
  80.   MOV DX,3D4h
  81.   JNZ @L1
  82.   MOV DX,3B4h
  83.  @L1:
  84.   MOV CRTAddress,DX
  85.   ADD DX,6
  86.   MOV StatusReg,DX
  87. END;
  88.  
  89.  
  90. {  The  VRAM  layout  is  this:  underneath  each  memory  address in the range
  91.   $A000:0000..$A000:$FFFF,  there  are  4 bytes, each representing one pixel's
  92.   color.
  93.   Whenever you write to or read from such an address, an internal logic of the
  94.   VGA-card determines which one of those 4 pixels is accessed.
  95.   A  line  of  320  pixels (=320 bytes) thus only takes 320/4=80 bytes address
  96.   space,  but  to  address  a pixel, you need a) its VRAM address and b) which
  97.   bitplane it's on.
  98.   The  pixels  are arranged linearly: thus, the mapping from point coordinates
  99.   to memory addresses is done by (x,y) <-> mem[$A000: y*80+ (x div 4)] and the
  100.   bitplane is determined by (x mod 4).
  101.   (Note coordinates start with 0 and that "div 4" can be computed very fast by
  102.   "shr 2"; "mod 4" by "and 3").
  103.  
  104.   So  you  computed the proper address and bitplane. If you want to _read_ the
  105.   pixel's color, you issue commands like this:
  106.    portw[$3CE]:=(bitplane SHL 8)+4; color:=mem[$A000:y*80+(x shr 2)]
  107.   Or for better speed & control, do it in ASM: }
  108.  MOV AL,4
  109.  MOV AH,bitplane
  110.  MOV DX,3CEh
  111.  CLI
  112.  OUT DX,AX
  113.  MOV AL,ES:[DI]
  114.  STI
  115.  
  116. {  _Writing_  a pixel's color works similiar, but needs an additional step: the
  117.   mask is computed by 1 SHL bitplane (that is: 1/2/4/8 for mod4 values 0/1/2/3
  118.   respectively):
  119.    portw[$3C4]:=(1 SHL bitplane+8)+2; mem[$A000:y*80+(x shr 2)]:=color
  120.   Or using ASM again: }
  121.  MOV CL,bitplane
  122.  MOV AH,1
  123.  SHL AH,CL
  124.  MOV AL,2
  125.  MOV DX,3C4h
  126.  CLI
  127.  OUT DX,AX
  128.  STOSB
  129.  STI
  130.  
  131. {  As  stated  above, one address represents 4 pixels, so 320x200 pixels occupy
  132.   16000  address  bytes.  We  do  have  65536  (=$A000:0..$A000:$FFFF) though,
  133.   therefore  a  bit  more  than 4 pages are possible. It's up to you to define
  134.   your  pages,  0..15999=page  0,  16000..31999=page  1,  32000..47999=page 2,
  135.   48000..63999=page 3, 64000..65535=unused  is the most obvious layout.
  136.  
  137.   Which  part  of  the VRAM is actually displayed can be programmed by writing
  138.   the  offset  part of the starting address to the CRT-controller (the segment
  139.   part is implicitly set to $A000): }
  140.  
  141. ASM
  142.   MOV DX,CRTAddress
  143.   MOV AL,$0D
  144.   CLI
  145.   OUT DX,AL
  146.   INC DX
  147.   MOV AL,low byte of starting offset
  148.   OUT DX,AL
  149.   DEC DX
  150.   MOV AL,$0C
  151.   OUT DX,AL
  152.   INC DX
  153.   MOV AL,high byte of starting offset
  154.   OUT DX,AL
  155.   STI
  156. END;
  157.  
  158. {
  159.   N.B.: if you reprogram the display's starting address more often than "every
  160.   now  and  then",  you  better  synchronize  that  to the vertical retrace or
  161.   horizontal  enable  signal  of  your VGA card; otherwise, an annoying screen
  162.   flicker will become visible during switching!
  163.  
  164.  
  165.   For  example,  if  you do a "FOR i:=1 TO 100 DO SetAddress(i*80)", this will
  166.   result  in a blinding fast hardware scroll: with each iteration of the loop,
  167.   the  display will start 80 address bytes (=320 pixels = 1 row) later, giving
  168.   the impression of the display scrolling upwards.
  169.  
  170.   Note  that  Mode  X/Y  do  not differ in any other respect than their memory
  171.   layouts  from  all  the  other  bitplaned VGA modes: palette handling is the
  172.   same,  as  is usage of the VGA's write modes! In (default) write mode 0, you
  173.   can access the VRAM by bytes, words or dwords. Write mode 1 is handy to copy
  174.   the  contents  of  one  graphic  page to another: you are restricted to byte
  175.   accesses, but each one will transfer 4 bytes at once.
  176.   For example, a sequence like the following...
  177.   portw[$3C4]:=$0f02; portw[$3CE]:=$4105;
  178.   move(mem[$a000:0000],mem[$a000:$3e80],16000);
  179.   portw[$3CE]:=$4005
  180.   ...enables  all 4 planes, switches to write mode 1, copies the (64000 bytes)
  181.   contents  of  the  2nd graphic page to the 1st one and then switches back to
  182.   write mode 0 again. }